#include "internal.h"
#include "probe.h"
#include "../scheme.h"
#include "../../common/pid_ctx.h"
#include "../../common/genTable.h"
#include "../xHookProc.h"
#include "../xLsmHook.h" 
#include "../ProtectFile.h" 
#include "../scriptfilter.h"
#include "../iNodeCtxTable.h"
#include "securityhook.h"
#include "../hook.h" 

#include "../globals.h" 


/*
    security_task_kill
*/
int ccs_task_kill(struct task_struct *p, struct siginfo *info,
			int sig, u32 secid)
{
    int ret;

   

    ret = securityhook_task_kill(p,info,sig,secid);

    return ret;

   
}

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)

/**
 * ccs_file_open - Check permission for open().
 *
 * @f:    Pointer to "struct file".
 * @cred: Pointer to "struct cred".
 *
 * Returns 0 on success, negative value otherwise.
 */
static int ccs_file_open(struct file *f, const struct cred *cred)
{
    int ret;
    

    ret = securityhook_file_open(f, cred);

        return ret;
    
    
}

#else

/**
 * ccs_dentry_open - Check permission for open().
 *
 * @f:    Pointer to "struct file".
 * @cred: Pointer to "struct cred".
 *
 * Returns 0 on success, negative value otherwise.
 */
static int ccs_dentry_open(struct file *f, const struct cred *cred)
{
    int ret;
    ret = securityhook_file_open(f, cred);
    return ret;
    
    
}

#endif

#if defined(CONFIG_SECURITY_PATH)


/**
 * ccs_path_truncate - Check permission for truncate().
 *
 * @path: Pointer to "struct path".
 *
 * Returns 0 on success, negative value otherwise.
 */
static int ccs_path_truncate(
        #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
            struct path *path
        #else
            struct path *path,
            loff_t length,
            unsigned int time_attrs
        #endif
    )
{
    int ret;

#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)

    ret = securityhook_path_truncate(path,0,0);
#else

ret = securityhook_path_truncate(path,length,time_attrs);

#endif
    
    return ret;
    
    

}
#endif

int wlSecMMapCheck(struct file * file, unsigned long reqprot,
			     unsigned long prot, unsigned long flags);
				 
int ccs_inode_alloc_security(struct inode *inode)
{
	int retval = 0;
	
	if(0==retval){
		insert_sys_inode(inode);
	}
	
	return retval;
}

void ccs_inode_free_security(struct inode *inode)
{
	
	remove_sys_inode_ctx(inode);
	
}

int ccs_inode_unlink(struct inode *dir, struct dentry *dentry)
{
    int ret;
    
    
    ret = securityhook_inode_unlink(dir, dentry);

    return ret;
    
    
}

int ccs_inode_rmdir(struct inode *dir, struct dentry *dentry)
{
    int ret;
    
	
    ret = securityhook_inode_rmdir(dir, dentry);


    return ret;
   
    
}

int ccs_inode_rename(struct inode *old_dir, struct dentry *old_dentry,
            struct inode *new_dir,
            struct dentry *new_dentry)
{
    int ret;
    
	
    ret = securityhook_inode_rename(old_dir, old_dentry, new_dir, new_dentry);

    
    return ret;
    
}

int ccs_inode_mkdir(struct inode *dir, struct dentry *dentry,
                        #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) // check-linux-src haozelong for ubuntu12 kernel:3.2.0
                            umode_t mode
                        #else
                            int mode
                        #endif
                            )
{
    int ret;


    ret = securityhook_inode_mkdir(dir, dentry, mode);

  
    return ret;
    
 
}

int ccs_inode_mknod(struct inode *dir, struct dentry *dentry,
                       #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) // check-linux-src haozelong for ubuntu12 kernel:3.2.0
                           umode_t mode,
                       #else
                           int mode,
                       #endif
				           dev_t dev)
{
    int ret;


    ret = securityhook_inode_mknod(dir, dentry, mode, dev);

    return ret;
    
 
}

int ccs_inode_create(struct inode *dir,
                             struct dentry *dentry,  
                         #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) // check-linux-src haozelong for ubuntu12 kernel:3.2.0
                             umode_t mode
                         #else
                             int mode
                        #endif
                             )
{
    int ret;
    
    ret = securityhook_inode_create(dir, dentry, mode);


    return ret;
   

}     
/* soft link */
int ccs_inode_symlink(struct inode *dir, struct dentry *dentry,
			    const char *old_name)
{
    int ret;
 
    ret = securityhook_inode_symlink(dir, dentry, old_name);

    
     return ret;
     

} 
/* hardlink */
int ccs_inode_link(struct dentry *old_dentry, struct inode *dir,
			 struct dentry *new_dentry)
{
    int ret;
 
    ret = securityhook_inode_link(old_dentry, dir, new_dentry);

 
     return ret;
     

} 



int ccs_inode_permission (struct inode *inode, int mask)
{
    int ret;
    ret = securityhook_inode_permission(inode, mask);
    return ret;


}
int ccs_file_permission (struct file *file, int mask)
{
    int ret;
    ret = securityhook_file_permission(file, mask);
    return ret;


}

static int ccs_mmap_file(struct file *file,
	  unsigned long reqprot, unsigned long prot,
	  unsigned long flags)
{
	int retval = 0;
    retval = securityhook_file_mmap(file, reqprot, prot, flags);

    if (retval)
    {
        return retval;
    }
    

	return retval;
}
#ifdef CONFIG_SECURITY_PATH 
 static int ccs_path_unlink(struct path *dir, struct dentry *dentry)
 {
 
     int ret;
 
     ret = securityhook_path_unlink(dir, dentry); 
     return ret;
 }
 static int ccs_path_rmdir(struct path *dir, struct dentry *dentry)
 {
     int ret;
     
     ret = securityhook_path_rmdir(dir, dentry);
     return ret;
     
 
 }
 
 
 
 
 static int ccs_path_rename(struct path *old_dir, struct dentry *old_dentry,
                  struct path *new_dir, struct dentry *new_dentry)
 {
 
     int ret;
 
     ret = securityhook_path_rename(old_dir, old_dentry, new_dir, new_dentry);
     return ret;
 }
 
 static int ccs_path_mkdir(const struct path *dir, struct dentry *dentry, int mode)
 {
     int ret;
     
     ret = securityhook_path_mkdir(dir, dentry, mode);
     return ret;
    
 }
 
 
 static int ccs_path_mknod(struct path *dir, struct dentry *dentry, int mode,
                unsigned int dev)
 {

    int ret;
    
    ret = securityhook_path_mknod(dir, dentry, mode, dev);
    return ret;  
 }
 
 static int ccs_path_symlink(struct path *dir, struct dentry *dentry,
                   const char *old_name)
 {
 
    int ret;

    ret = securityhook_path_symlink(dir, dentry, old_name);

    return ret;
     
 }
 
 static int ccs_path_link(struct dentry *old_dentry, struct path *new_dir,
                    struct dentry *new_dentry)
 {
 
    int ret;

    ret = securityhook_path_link(old_dentry, new_dir, new_dentry);
 
    return ret;
      
 }
 
#endif 


#include <linux/mman.h>

 int ccs_bprm_set_creds(struct linux_binprm *bprm)
{
	int ret;

    ret = securityhook_bprm_set_creds(bprm);
    return ret;
    

}

 static ssize_t __xkernel_write(struct file *file, const char *buf, size_t count,
			    loff_t pos)
{
	mm_segment_t old_fs;
	ssize_t res;

	old_fs = get_fs();
	set_fs(get_ds());
	/* The cast to a user pointer is valid due to the set_fs() */
	res = vfs_write(file, (const char __user *)buf, count, &pos);
	set_fs(old_fs);

	return res;
}


int ccs_bprm_check_security(struct linux_binprm *bprm)
{
    int ret;
    
    ret = securityhook_bprm_check_security(bprm);

    
    return ret;
    

}

struct security_operations kylin_security_ops = {
	.name                   = "Wnt",
	.bprm_check_security    = ccs_bprm_check_security,
	.task_kill              = ccs_task_kill,
	.file_open              = ccs_file_open,
#if defined(CONFIG_SECURITY_PATH)
	.path_truncate          = ccs_path_truncate,
	.path_link     = ccs_path_link,
    .path_unlink   = ccs_path_unlink,
    .path_symlink  = ccs_path_symlink,
    .path_mkdir    = ccs_path_mkdir,
    .path_rmdir    = ccs_path_mkdir,
    .path_mknod    = ccs_path_mknod,
    .path_rename   = ccs_path_rename,
#endif	
	.inode_alloc_security   = ccs_inode_alloc_security,
	.inode_free_security    = ccs_inode_free_security,
	.inode_unlink           = ccs_inode_unlink,
	.inode_rmdir            = ccs_inode_rmdir,
	.inode_rename           = ccs_inode_rename,
	.inode_mkdir            = ccs_inode_mkdir,
	.inode_mknod            = ccs_inode_mknod,
	.inode_create           = ccs_inode_create,
	.inode_symlink          = ccs_inode_symlink,
	.inode_link             = ccs_inode_link,
	.inode_permission       = ccs_inode_permission,
	.file_permission        = ccs_file_permission,
	.mmap_file              = ccs_mmap_file,
	//.bprm_set_creds         = ccs_bprm_set_creds,//BUG40274
};

int ccs_init(void)
{

    int ret;
#ifdef CONFIG_SECURITY_PATH
        printk(KERN_INFO "%s:%s:%d CONFIG_SECURITY_PATH\n",__FILE__,__func__,__LINE__);
#else
        printk(KERN_INFO "%s:%s:%d !CONFIG_SECURITY_PATH\n",__FILE__,__func__,__LINE__);
    
#endif
    ret = register_secondary_security(&kylin_security_ops);
    printk(KERN_INFO "[%s:%d] register_secondary_security %d\n",__func__,__LINE__,ret);
    if(ret != 0 )
    {
        printk(KERN_ERR "[%s:%d] \n",__func__,__LINE__);
    }
    return ret;

}
int ccs_destroy(void)
{
    int ret;
     ret= unregister_secondary_security(&kylin_security_ops);
    printk(KERN_ERR "[%s:%d] register_secondary_security %d\n",__func__,__LINE__,ret);
    
    return ret;
}


